package com.tcoiss.app.service.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.tcoiss.app.domain.*;
import com.tcoiss.app.service.IElectronicFenceService;
import com.tcoiss.app.service.IFenceDistrictService;
import com.tcoiss.app.service.IFencePointsService;
import com.tcoiss.app.service.ITrackServiceService;
import com.tcoiss.common.core.enums.ErroEnums;
import com.tcoiss.common.core.exception.CustomException;
import com.tcoiss.common.core.utils.SecurityUtils;
import com.tcoiss.common.core.web.domain.AjaxResult;
import com.tcoiss.app.mapper.FencePointsMapper;
import com.tcoiss.app.utils.SplitList;
import com.tcoiss.common.component.api.model.AddressVo;
import com.tcoiss.common.component.service.ApiHelperService;
import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.io.UnsupportedEncodingException;
import java.lang.reflect.InvocationTargetException;
import java.net.URLEncoder;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 轨迹服务配置Service业务层处理
 *
 * @author zw
 * @date 2021-02-21
 */
@Service
@Transactional
public class FencePointsServiceImpl extends ServiceImpl<FencePointsMapper, FencePoints> implements IFencePointsService {

    @Autowired
    private IElectronicFenceService iElectronicFenceService;

    @Autowired
    private ITrackServiceService iTrackServiceService;

    @Resource
    private IFenceDistrictService iFenceDistrictService;

    @Autowired
    private ApiHelperService apiHelperService;


    /**
     * 查询所有的围栏
     * @param electronicFence
     * @return
     */
    @Override
    public List<ElectronicFence> queryList(ElectronicFence electronicFence) {
        //全表查询时查询缓存是否存在
        LambdaQueryWrapper<ElectronicFence> lqw = Wrappers.lambdaQuery();
        if(StringUtils.isNotBlank(electronicFence.getFenceName())){
            lqw.like(ElectronicFence::getFenceName, electronicFence.getFenceName());
        }
        if(StringUtils.isNotBlank(electronicFence.getAdcode())){
            lqw.eq(ElectronicFence::getAdcode, electronicFence.getAdcode());
        }
        if(StringUtils.isNotBlank(electronicFence.getCityCode())){
            lqw.eq(ElectronicFence::getCityCode, electronicFence.getCityCode());
        }
        if(electronicFence.getFencePop() != null){
            lqw.like(ElectronicFence::getFencePop, electronicFence.getFencePop());
        }else {
            lqw.like(ElectronicFence::getFencePop,iFenceDistrictService.getTowsPopByRole().get(0));
        }
        List<ElectronicFence> list1 = iElectronicFenceService.list(lqw);
        return list1;
    }

    @Override
    public AjaxResult saveOrUpdateFence(ElectronicFence fence) {
        if(StringUtils.isBlank(fence.getFenceCode())){
            String code = "4"+ LocalDateTime.now().format(DateTimeFormatter.ofPattern("HHmmss"));
            // todo 更据围栏坐标重新拆分围栏,获取剩余区域围栏的坐标
            List newDistrictPaths;
            Map<String,Object> result = new HashMap<>();
            try {
                newDistrictPaths = SplitList.naiveSplitSame(fence.getDistrictPointList(),fence.getPointList());
                //根据区域ID查询区域信息
                FenceDistrict fenceDistrict = iFenceDistrictService.getById(fence.getDistrictId());
                if(newDistrictPaths == null){
                    fenceDistrict.setDistrictPoints("");
                }else{
                    fenceDistrict.setDistrictPoints(SplitList.getPointsByList(newDistrictPaths));
                }
                fence.setCity(fenceDistrict.getCity());
                fence.setCityCode(fenceDistrict.getCityCode());
                fence.setAdcode(fenceDistrict.getAdcode());
                fence.setAdcodeName(fenceDistrict.getAdcodeName());
                fence.setFenceCode(code);
                fence.setFencePop(fenceDistrict.getDistrictPop().toString());
                String fenceName = fenceDistrict.getCity() + fenceDistrict.getAdcodeName() + fenceDistrict.getDistrictName();
                fence.setFenceName(fenceName + getFenceNumByQYId(fenceDistrict.getId()));
                        fence.setFenceColor(fenceDistrict.getDistrictColor());
                return  this.saveByFence(fenceDistrict,fence,"createFenceNew");
            }catch (Exception e){
                result.put("code",500);
                result.put("message",e.toString());
                return AjaxResult.success(result);
            }
        }else{
            //根据编码查询查询到则修改，未查询到则新增
            ElectronicFence fence1 = iElectronicFenceService.getByFenceCode(fence.getFenceCode());
            if(fence1.equals(fence)){//未修改则直接返回，修改了则保存当前围栏对象
                return AjaxResult.success();
            }
            return this.updateByFence(fence,"updateFenceNew");
        }

    }

    @Override
    public boolean copyElectronicFence(ElectronicFence electronicFence){
        if(iElectronicFenceService.updateById(electronicFence)){
            return iElectronicFenceService.syncFence(electronicFence,1) ? true : false;
        }
        return false;
    }



    @Override
    public AjaxResult queryAdminByLocations(String location) {
        //调用逆地理位置接口查询行政区划
        TrackService trackService = iTrackServiceService.getDefaultKey();
        Map<String,Object> params = new HashMap<>();
        params.put("key",trackService.getGaodeKey());
        params.put("location",location);
        //通过地址关键字查询地址列表
        Map<String,Object> result = apiHelperService.executeApi("getAddressByLocation",params);
        if(result == null){
            //return AjaxResult.error(204,"获取地址列表错误：http请求连接异常");
            return AjaxResult.error(ErroEnums.APIERRO.getCode(),"获取地址列表错误：http请求连接异常");
        }else {
            if (Integer.valueOf(result.get("status").toString()) == 1) {//创建成功
                AddressVo vo = new AddressVo();
                Map<String, Object> regeocode = (Map<String, Object>) result.get("regeocode");
                String address = regeocode.get("formatted_address").toString();
                Map<String,Object> addressComponent = (Map<String, Object>) regeocode.get("addressComponent");
                try {
                    BeanUtils.populate(vo, addressComponent);
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                    return AjaxResult.success("系统异常");
                } catch (InvocationTargetException e) {
                    e.printStackTrace();
                    return AjaxResult.error("系统异常");
                }
                //vo.setAddress(address);
                return AjaxResult.success("成功",vo);
            }else{
                //AjaxResult.error(408,"获取地址列表异常："+result.get("info").toString());
                return AjaxResult.error(ErroEnums.APIERRO.getCode(),"获取地址列表异常："+result.get("info").toString());
            }
        }
    }



    @Override
    public int updateByCode(ElectronicFence fence) {
        if(!checkFenceName(fence)){
            if(iElectronicFenceService.updateById(fence)){
                return iElectronicFenceService.syncFence(fence,1)?1:0;
            }
        }else {
            throw new CustomException(ErroEnums.DATAERRO.getCode(),new Object[]{},ErroEnums.DATAERRO.getInfo() + "围栏名称已存在");
        }
        return 0;
    }

    private int getFenceNumByQYId(Long id){
        Map<String,Object> map = new HashMap<>();
        map.put("district_id" , id);
        List<ElectronicFence> fd = iElectronicFenceService.listByMap(map);
        return fd.size()+1;
    }


    private AjaxResult saveByFence(FenceDistrict fenceDistrict,ElectronicFence fence, String apiCode) {
        // todo 查询区域信息
        TrackService trackService = iTrackServiceService.getUsableKey();
        if(trackService==null){
            return AjaxResult.error(ErroEnums.BUSERRO.getCode(),"保存围栏失败无可用key");
        }
        //先分配服务ID再调接口再保存到本地入库
        FenceVo vo = new FenceVo();
        vo.setName(fence.getFenceName());
        vo.setKey(trackService.getGaodeKey());
        vo.setDesc(fence.getFenceDesc());
        vo.setPoints(fence.getFencePoints());
        Map resultMap = apiHelperService.executeApi(apiCode,vo);
        if(resultMap == null){
            return AjaxResult.error(ErroEnums.APIERRO.getCode(),"http请求连接异常");
        }else{
            if(Integer.valueOf(resultMap.get("errcode").toString())==0) {//创建成功
                Map<String, Object> dataMap = JSON.parseObject(resultMap.get("data").toString());
                if(Integer.valueOf(dataMap.get("status").toString()) == 0){

                    String gid = dataMap.get("gid").toString();
                    fence.setGdId(gid);
                    fence.setGaodeKey(trackService.getGaodeKey());
                    //将平台gfid更新到数据库中并在服务配置中加1
                    iTrackServiceService.addFenceNum(trackService,1);
                    //更新区域坐标
                    iFenceDistrictService.updateById(fenceDistrict);
                    //保存坐标数据
                    /*this.saveBatch(pointsList);*/
                    fence.setCreateor(SecurityUtils.getUsername());
                    fence.setCreateorId(SecurityUtils.getUserId());
                    Map<String,Object> result = new HashMap<>();
                    result.put("code",200);
                    result.put("message","成功");
                    int num = iElectronicFenceService.syncFence(fence,1)?1:0;
                    result.put("num",num);
                    return AjaxResult.success(result);
                }else{
                    Map<String,Object> result = new HashMap<>();
                    result.put("code",500);
                    result.put("message","接口调用异常："+dataMap.get("message").toString());
                    return AjaxResult.success(result);
                }
            }else{
                // AjaxResult.error(206,"接口调用异常："+resultMap.get("errmsg").toString());
                return AjaxResult.error(ErroEnums.APIERRO.getCode(), "接口调用异常："+resultMap.get("errmsg").toString());
            }
        }
    }

    private AjaxResult updateByFence(ElectronicFence electronicFence, String apiCode) {
        FenceVo vo = new FenceVo();
        vo.setName(electronicFence.getFenceName());
        vo.setGid(electronicFence.getGdId());
        vo.setKey(electronicFence.getGaodeKey());
        String points = electronicFence.getFencePoints();
        vo.setPoints(points);
        Map resultMap = apiHelperService.executeApi(apiCode,vo);
        if(resultMap == null){
            // AjaxResult.error(204,"http请求连接异常");
            return AjaxResult.error(ErroEnums.APIERRO.getCode(),"http请求连接异常");
        }else{
            if(Integer.valueOf(resultMap.get("errcode").toString())==0) {//创建成功
                Map<String, Object> dataMap = JSON.parseObject(resultMap.get("data").toString());
                if(Integer.valueOf(dataMap.get("status").toString()) == 0) {
                    Map<String,Object> result = new HashMap<>();
                    result.put("code",200);
                    result.put("message","成功");
                    int num = iElectronicFenceService.syncFence(electronicFence,1) ? 1 : 0;
                    result.put("num",num);
                    return AjaxResult.success(result);
                    //更新本地数据
                }else{
                    Map<String,Object> result = new HashMap<>();
                    result.put("code",500);
                    result.put("message","接口调用异常："+dataMap.get("message").toString());
                    return AjaxResult.success(result);
                }
            }else{
                //AjaxResult.error(206,"接口调用异常："+resultMap.get("errmsg").toString());
            return AjaxResult.error(ErroEnums.APIERRO.getCode(), "接口调用异常："+resultMap.get("errmsg").toString());
            }
        }
    }

    @Override
    public AjaxResult getFenceByLocation(AddressVo addressVo) {
        Map<String ,Object> map = new HashMap<>();
        try {
            String address = URLEncoder.encode(addressVo.getAddress(),"utf-8");
            map.put("address",address);
        } catch (UnsupportedEncodingException e) {
            return AjaxResult.error(ErroEnums.SYSERRO.getCode(), "系统异常");
        }
        map.put("city","");
        map.put("key",iTrackServiceService.getDefaultKey().getGaodeKey());
        Map resultMap = apiHelperService.executeApi("geocode", map);
        if (resultMap == null) {
            // AjaxResult.error(404,"获取地址坐标请求连接异常");
            return AjaxResult.error(ErroEnums.APIERRO.getCode(), "获取地址坐标请求连接异常");
        } else {
            if (Integer.valueOf(resultMap.get("status").toString()) == 1) {//成功
                //获取地址坐标数据
                List<Map<String, Object>> geocodes = (List<Map<String, Object>>) resultMap.get("geocodes");
                if(geocodes==null||geocodes.size()==0){
                    // AjaxResult.error(408,"无法解析地址信息");
                    return AjaxResult.error(ErroEnums.APIERRO.getCode(), "无法解析地址信息");
                }
                Map<String, Object> geocode = geocodes.get(0);
                String location = geocode.get("location").toString();
                String province = geocode.get("province").toString();
                if(geocode.get("city")==null){
                    // AjaxResult.error(407,"根据地址信息无法定位城市");
                    return AjaxResult.error(ErroEnums.APIERRO.getCode(), "根据地址信息无法定位城市");
                }
                String city = geocode.get("city").toString();
                String cityCode = geocode.get("citycode").toString();
                String district = geocode.get("district").toString();
                String adCode = geocode.get("adcode").toString();
                String street = geocode.get("street").toString();
                Map<String, Object> param = new HashMap<>();
                //先更据城市编码，区域编码查询gids
                LambdaQueryWrapper<ElectronicFence> lqw = Wrappers.lambdaQuery();
                lqw.eq(ElectronicFence::getCityCode,cityCode);
                //lqw.eq(ElectronicFence::getFencePop,addressVo.getAddressPop());
                lqw.eq(ElectronicFence::getAdcode,adCode);
                lqw.select(ElectronicFence::getGaodeKey,ElectronicFence::getCityCode,ElectronicFence::getFencePop,ElectronicFence::getAdcode);
                lqw.groupBy(ElectronicFence::getGaodeKey,ElectronicFence::getCityCode,ElectronicFence::getFencePop,ElectronicFence::getAdcode);
                List<ElectronicFence> fences = iElectronicFenceService.list(lqw);
                List<String> keys = fences.stream().map(fence -> fence.getGaodeKey()).collect(Collectors.toList());
                return getFencesByKey(keys,location);
            } else {
                return AjaxResult.error(ErroEnums.APIERRO.getCode(), "获取地址坐标接口异常："+resultMap.get("info").toString());
            }

        }
    }
    //调用围栏检测接口
    private AjaxResult getFencesByKey(List<String> keys,String location){
        List<Map<String,Object>> list = new ArrayList<>();
        Map<String, Object> param = new HashMap<>();
        param.put("diu", "176070919621234");
        param.put("locations", location + "," + System.currentTimeMillis()/1000L);
        //param.put("gfids",String.join(",",gfids));
        for(String key:keys){
            param.put("key", key);
            Map resultMap2 = apiHelperService.executeApi("monitorFenceNew", param);
            if (resultMap2 == null) {
                //return AjaxResult.error(405,"根据地址获取围栏请求连接异常");
                //throw new ApiException("405",new Object[]{},"根据地址获取围栏请求连接异常");
            } else {
                if (Integer.valueOf(resultMap2.get("errcode").toString()) == 0) {//成功
                    Map<String,Object> dataMap = (Map<String, Object>) resultMap2.get("data");
                    if(Integer.valueOf(dataMap.get("status").toString()) == 0){
                        if(dataMap.get("nearest_fence_gid")!=null){
                            Map<String,Object> resultJoson = new HashMap<>();
                            LambdaQueryWrapper<ElectronicFence> lqw = Wrappers.lambdaQuery();
                            lqw.eq(ElectronicFence::getGdId,dataMap.get("nearest_fence_gid"));
                            /*lqw.eq(ElectronicFence::getGdId,addressVo.getAddressPop());*/
                            List<ElectronicFence> fences0 = iElectronicFenceService.list(lqw);
                            if(fences0!=null&&fences0.size()>0){
                                resultJoson.put("fenceName",fences0.get(0).getFenceName());
                                resultJoson.put("fenceCode",fences0.get(0).getFenceCode());
                                /*resultJoson.put("province",province);
                                resultJoson.put("district",district);
                                resultJoson.put("city",city);
                                resultJoson.put("street",street);*/
                                list.add(resultJoson);
                            }

                        }
                        List<Map<String,Object>> fencingEvents = (List<Map<String, Object>>) dataMap.get("fencing_event_list");
                        fencingEvents.forEach(result->{
                            if(result.get("client_status").toString().equals("in")){
                                //根据地址信息查询地址坐标
                                Map fenceInfo = (Map) result.get("fence_info");
                                Map<String,Object> resultJoson = new HashMap<>();
                                String gid = fenceInfo.get("fence_gid").toString();
                                LambdaQueryWrapper<ElectronicFence> lqw = Wrappers.lambdaQuery();
                                lqw.eq(ElectronicFence::getGdId,gid);
                                //lqw.eq(ElectronicFence::getFencePop,addressVo.getAddressPop());
                                List<ElectronicFence> fences0 = iElectronicFenceService.list(lqw);
                                if(fences0!=null&&fences0.size()>0){
                                    resultJoson.put("fenceName",fences0.get(0).getFenceName());
                                    resultJoson.put("fenceCode",fences0.get(0).getFenceCode());
                                    /*resultJoson.put("province",province);
                                    resultJoson.put("district",district);
                                    resultJoson.put("city",city);
                                    resultJoson.put("street",street);*/
                                    list.add(resultJoson);
                                }
                            }
                        });

                    }else{
                        return AjaxResult.error(ErroEnums.APIERRO.getCode(), "根据地址获取围栏接口异常："+resultMap2.get("message"));
                    }

                }else{
                    return AjaxResult.error(ErroEnums.APIERRO.getCode(),"根据地址获取围栏接口异常："+resultMap2.get("errmsg"));
                }
            }
        }
        if(list.size()>1){
            return AjaxResult.error(ErroEnums.APIERRO.getCode(),"该地址落在多个围栏中");
        }
        if(list.size() == 0){
            return AjaxResult.error(ErroEnums.APIERRO.getCode(),"该地址未在围栏中");
        }
        return AjaxResult.success("成功",list.get(0));
    }


    @Override
    public boolean checkFenceName(ElectronicFence electronicFence) {

        return iElectronicFenceService.checkFenceName(electronicFence);
    }


    /**
     * 根据主键Id查询electronic_fence数据表的district_id字段,
     * 将其在围栏、苍穹、本地中同步删除
     * copyList无需删除围栏与苍穹数据,只需更新本地围栏与苍穹数据.
     * @param districtId(fence_district表的主键Id)
     */
    @Override
    public boolean removeByDistrictId(Long districtId) {
        if(districtId != null){
            Map<String,Object> map = new HashMap<>();
            map.put("district_id",districtId);
            List<ElectronicFence> ef = iElectronicFenceService.listByMap(map);
            LambdaQueryWrapper<ElectronicFence> lqw = Wrappers.lambdaQuery();
            lqw.eq(ElectronicFence::getIsCopy,1);
            lqw.eq(ElectronicFence::getAdcode,iFenceDistrictService.getById(districtId).getAdcode());
            List<ElectronicFence> copyList = iElectronicFenceService.list(lqw);
            for (ElectronicFence electronicFence : copyList){
                electronicFence.setFencePop("0");
                electronicFence.setIsCopy(0);
                if(iElectronicFenceService.updateById(electronicFence)){
                    iElectronicFenceService.syncFence(electronicFence,1);
                }
            }
            for (ElectronicFence  electronicFence : ef){
                removeByCode(electronicFence.getFenceCode(),"deleteFenceNew");
            }
            return true;
        }
        throw new CustomException(ErroEnums.BUSERRO.getCode(),new Object[]{},ErroEnums.BUSERRO.getInfo() + "区域ID不能为空");
    }

    @Override
    public AjaxResult saveFenceByQy(ElectronicFence fence) {
        if(!checkFenceName(fence)){
            String code = "gd_"+ LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyMMddHHmmss"));
            // todo 更据围栏坐标重新拆分围栏,获取剩余区域围栏的坐标
            //根据区域ID查询区域信息
            FenceDistrict fenceDistrict = iFenceDistrictService.getById(fence.getDistrictId());
            fence.setCity(fenceDistrict.getCity());
            fence.setCityCode(fenceDistrict.getCityCode());
            fence.setAdcode(fenceDistrict.getAdcode());
            fence.setAdcodeName(fenceDistrict.getAdcodeName());
            fence.setFencePoints(fenceDistrict.getDistrictPoints());
            fence.setFenceCode(code);
            fenceDistrict.setDistrictPoints("");
            return  this.saveByFence(fenceDistrict,fence,"createFenceNew");
        }else{
            throw new CustomException(ErroEnums.DATAERRO.getCode(),new Object[]{},ErroEnums.DATAERRO.getInfo() + "围栏名称已存在");
        }

    }

    @Override
    public boolean removeByCode(String fenceCode,String apiCode) {
        ElectronicFence electronicFence = iElectronicFenceService.getByFenceCode(fenceCode);
        //
        Map<String,String> map = new HashMap<>();
        map.put("gid",electronicFence.getGdId());
        //TrackService trackService = this.getTrackService(electronicFence.getCityCode());
        //map.put("gid",trackService.getServiceId());
        map.put("key",electronicFence.getGaodeKey());
        Map resultMap = apiHelperService.executeApi(apiCode,map);
        if(resultMap == null){
            throw new CustomException("http请求连接异常",203);
        }else{
            if(Integer.valueOf(resultMap.get("errcode").toString())==0) {
                Map<String,Object> dataMap = (Map<String, Object>) resultMap.get("data");
                if(Integer.valueOf(dataMap.get("status").toString()) == 0){
                    //围栏数量减一
                    TrackService trackService = iTrackServiceService.getOneByKey(electronicFence.getGaodeKey());
                    iTrackServiceService.addFenceNum(trackService,-1);
                    //删除本地数据
                    return iElectronicFenceService.syncFence(electronicFence,0);
                }else{
                    throw new CustomException("接口调用异常："+dataMap.get("message").toString(),201);
                }
            }else{
                throw new CustomException("接口调用异常："+resultMap.get("errmsg").toString(),202);
            }
        }
    }



}
